﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RayTracer.Structures;
using RayTracer.Environment.Materials;
using System.Xml;

namespace RayTracer.Environment.Objects
{
    /// <summary>
    /// Modelliert ein Objekt
    /// </summary>
    [Serializable]
    public abstract class AObject
    {
        #region Attribute
        private Structures.Point position;
        private Vector rotation;
        private Material material = Material.Default;
        #endregion Attribute

        #region Eigenschaften
        /// <summary>
        /// Gibt und setzt die Position.
        /// </summary>
        public Structures.Point Position { get { return position; } set { position = value; } }

        /// <summary>
        /// Gibt und setzt die Rotation. (xyz-Bogenmaß)
        /// </summary>
        public Vector Rotation { get { return rotation; } set { rotation = value; } }

        /// <summary>
        /// Gibt und setzt das Material.
        /// </summary>
        public Material Material { get { return material; } set { material = value; } }
        #endregion Eigenschaften

        #region Methoden
        #region Typenumwandlung
        /// <summary>
        /// Gibt eine Zeichenkettenrepräsentation der Klasse zurück.
        /// </summary>
        /// <returns>Die Zeichenkette.</returns>
        public override string ToString()
        {
            return "Objekt @ " + Position.ToString();
        }

        /// <summary>
        /// Erstellt ein Objekt aus einem XML-Knoten.
        /// </summary>
        /// <param name="xmlNode">Das XML-Knoten.</param>
        /// <param name="obj">Das spezifische Objekt.</param>
        /// <returns>Das Objekt.</returns>
        internal static T FromXml<T>(XmlNode xmlNode, T obj) where T : AObject
        {
            XmlNode nodePosition = xmlNode.SelectSingleNode("Position");
            XmlNode nodeRotation = xmlNode.SelectSingleNode("Rotation");
            XmlNode nodeMaterial = xmlNode.SelectSingleNode("Material");
            if (nodePosition != null) obj.position = Point.FromXml(nodePosition);
            if (nodeRotation != null) obj.rotation = Vector.FromXml(nodeRotation);
            if (nodeMaterial != null) obj.material = Material.FromXml(nodeMaterial);
            return obj;
        }

        /// <summary>
        /// Wandelt das Objekt in einen XML-Knoten um.
        /// </summary>
        /// <param name="xmlDocument">Das zugrunde liegende XML-Dokument.</param>
        /// <returns>Der XML-Knoten.</returns>
        internal virtual XmlNode ToXml(XmlDocument xmlDocument)
        {
            XmlNode node = xmlDocument.CreateNode(XmlNodeType.Element, this.GetType().Name, null);
            node.AppendChild(position.ToXml(xmlDocument, "Position"));
            node.AppendChild(rotation.ToXml(xmlDocument, "Rotation"));
            node.AppendChild(material.ToXml(xmlDocument));
            return node;
        }
        #endregion Typenumwandlung
        #endregion Methoden
    }
}
